import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lib_uikit/lib_uikit.dart';

typedef GTRefreshListItemBuilder = Widget? Function(BuildContext context, int index, dynamic item);

class GTRefreshListView extends ConsumerStatefulWidget {
  final ScrollPhysics? physics;

  /// 列表的滚动控制器
  final ScrollController? controller;

  /// 列表的内边距
  final EdgeInsetsGeometry? padding;

  /// 当列表为空时，会显示[emptyViewBuilder]构建的组件
  /// 如果[emptyViewBuilder]为空，则显示[GTEmptyDataView]
  final WidgetBuilder? emptyViewBuilder;

  /// 当列表加载失败时，会显示[errorViewBuilder]构建的组件
  /// 如果[errorViewBuilder]为空，则显示[GTEmptyDataView]
  final WidgetBuilder? errorViewBuilder;

  /// 当列表没有数据，并且在加载中时，会显示[loadingViewBuilder]构建的组件
  final WidgetBuilder? loadingViewBuilder;

  /// 用户下拉刷新或者上拉加载时，会调用[modelFetcher]方法，获取数据
  final ModelFetcher modelFetcher;

  /// [itemBuilder]用于构建列表项, 用法跟 ListView 的 itemBuilder 类似,
  /// 但是多了一个参数 [item], 用于传递列表项的数据.
  final GTRefreshListItemBuilder itemBuilder;

  /// [separatorBuilder]用于构建列表项之间的分割线, 用法跟 ListView 的 separatorBuilder 相同
  final IndexedWidgetBuilder? separatorBuilder;

  /// 是否允许下拉刷新
  final bool enablePullDown;

  /// 是否允许上拉加载
  final bool enablePullUp;

  /// 是否在组件挂载时，自动请求第一页数据
  final bool requestFirstPageWhenMounted;

  /// 是否将列表的状态视图嵌入到列表中(空视图时可以下拉刷新)
  final bool embedStateViewInList;

  const GTRefreshListView({
    required this.modelFetcher,
    required this.itemBuilder,
    this.separatorBuilder,
    this.loadingViewBuilder,
    this.controller,
    this.physics,
    this.padding,
    this.emptyViewBuilder,
    this.errorViewBuilder,
    this.enablePullDown = true,
    this.enablePullUp = true,
    this.requestFirstPageWhenMounted = true,
    this.embedStateViewInList = false,
    super.key,
  });

  @override
  ConsumerState<ConsumerStatefulWidget> createState() => GTRefreshListViewState();
}

class GTRefreshListViewState extends ConsumerState<GTRefreshListView> {
  late GTListConfig listConfig;

  List<dynamic> get list => ref.read(_listenable).list;

  GTListControllerProvider get _listenable => gTListControllerProvider(config: listConfig);

  GTListController get listController => ref.read(_listenable.notifier);

  GTListState get listState => ref.read(_listenable);

  final _refresherKey = GlobalKey<GTRefresherState>();

  @override
  void initState() {
    super.initState();
    listConfig = GTListConfig(modelFetcher: widget.modelFetcher);
    if (widget.requestFirstPageWhenMounted) {
      WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
        if (mounted) {
          listController.requestFirstPage();
        }
      });
    }
  }

  requestFirstPage({bool pullDownAnimation = false, Map<String, String>? params}) {
    if (pullDownAnimation) {
      _refresherKey.currentState?.refreshController.requestRefresh();
    } else {
      listController.requestFirstPage();
    }
  }

  insertModel(dynamic model, int index) {
    listController.insertModel(model, index);
  }

  removeModelAt(int index) {
    listController.removeModelAt(index);
  }

  updateModel(dynamic model, int index) {
    listController.updateModel(model, index);
  }

  updateList(List dataList) {
    listController.updateList(dataList);
  }

  Widget _buildEmptyView(BuildContext context) =>
      widget.emptyViewBuilder != null ? widget.emptyViewBuilder!(context) : const GTEmptyDataView();

  Widget _buildErrorView(BuildContext context) =>
      widget.errorViewBuilder != null ? widget.errorViewBuilder!(context) : const GTEmptyDataView();

  Widget _buildLoadingView(BuildContext context) =>
      widget.loadingViewBuilder != null ? widget.loadingViewBuilder!(context) : const GTLoadingView();

  @override
  Widget build(BuildContext context) {
    var listState = ref.watch(gTListControllerProvider(config: listConfig));

    if (listState.list.isEmpty) {
      if (listState.isLoading) {
        return _buildLoadingView(context);
      }
      if (!widget.embedStateViewInList) {
        return _buildStateView();
      }
    }

    return GTRefresher(
      key: _refresherKey,
      enablePullDown: widget.enablePullDown,
      enablePullUp: widget.enablePullUp ? listState.hasMoreData : false,
      onRefresh: listController.requestFirstPage,
      onLoading: listController.requestNextPage,
      child: (listState.list.isEmpty && widget.embedStateViewInList)
          ? _buildStateView()
          : ListView.separated(
              physics: widget.physics,
              controller: widget.controller,
              padding: widget.padding,
              itemBuilder: ((context, index) {
                return widget.itemBuilder(context, index, listState.list[index]);
              }),
              separatorBuilder: (context, index) {
                if (widget.separatorBuilder != null) {
                  return widget.separatorBuilder!(context, index);
                } else {
                  return const SizedBox.shrink();
                }
              },
              itemCount: listState.list.length,
            ),
    );
  }

  Widget _buildStateView() {
    if (listState.errorMessage != null) {
      return _buildErrorView(context);
    } else {
      return _buildEmptyView(context);
    }
  }
}
